/**
 * 
 */
package com.gr.staffpm.notes;

import java.util.List;

import org.apache.shiro.SecurityUtils;
import org.apache.wicket.ajax.AbstractDefaultAjaxBehavior;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.MarkupStream;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.markup.repeater.RepeatingView;
import org.apache.wicket.model.Model;
import org.apache.wicket.spring.injection.annot.SpringBean;
import org.joda.time.DateTime;

import com.gr.notes.cometd.CometdPushService;
import com.gr.notes.core.push.AbstractPushEventHandler;
import com.gr.notes.core.push.IPushChannel;
import com.gr.notes.core.push.IPushEventHandler;
import com.gr.notes.core.push.IPushService;
import com.gr.staffpm.datatypes.User;
import com.gr.staffpm.notes.activity.Activity;
import com.gr.staffpm.notes.activity.ActivityMessage;
import com.gr.staffpm.notes.activity.listener.IActivityListener;
import com.gr.staffpm.notes.activity.service.IActivityDaoService;
import com.gr.staffpm.notes.push.ActivityService;
import com.gr.staffpm.pages.login.Login;
import com.gr.staffpm.pages.notes.AllUserNotesPage;
import com.gr.staffpm.security.service.UserService;


/**
 * @author Graham Rhodes 19 Feb 2011 20:31:46
 */
public class NotesPanel extends Panel {

    private static final long serialVersionUID = 1L;
    @SpringBean(name = "activityService")
    private IActivityDaoService activityDaoService;
    @SpringBean(name = "userService")
    private UserService userService;
    private final IPushEventHandler<ActivityMessage> handler;
    private final IPushChannel<ActivityMessage> pushChannel;
    private final RepeatingView notifications = new RepeatingView("notifications");
    private final WebMarkupContainer notificationsWrapper = new WebMarkupContainer("notificationsWrapper");
    private final WebMarkupContainer notesBoxNotif = new WebMarkupContainer("notesBoxNotif");
    private final Label notesNewCount = new Label("notesNewCount", new Model<String>());

    public NotesPanel(String id) {
        super(id);

        notificationsWrapper.setOutputMarkupId(true);
        notesBoxNotif.setOutputMarkupId(true);
        notifications.setOutputMarkupId(true);

        //Called from jqueryslidemenu.js on hover out
        notificationsWrapper.add(new AbstractDefaultAjaxBehavior() {

            private static final long serialVersionUID = 1L;

            @Override
            protected void respond(AjaxRequestTarget target) {
                updateActivitiesToOld(target);
            }
        });

        handler = new AbstractPushEventHandler<ActivityMessage>() {

            private static final long serialVersionUID = 1L;

            @Override
            public void onEvent(final AjaxRequestTarget target, final ActivityMessage message) {
                updateNotifications(target);
            }
        };

        /*
         * 2. obtain a reference to a Push service implementation
         */
        final IPushService pushService = CometdPushService.get();

        /*
         * 3. install push channel into this panel
         */
        pushChannel = pushService.installPushChannel(this, handler);

        final User currentUser = userService.getCurrentUser();

        /*
         * 4. connect to the activity service and forward the ActivityMessage events
         */
        ActivityService.getInstance().addListener(currentUser, new IActivityListener() {

            @Override
            public void onMessage(ActivityMessage msg) {
                if (pushService.isConnected(pushChannel)) {
                    // forward the Message event via the push service to the push event handler
                    pushService.publish(pushChannel, msg);
                } else {
                    ActivityService.getInstance().removeListener(currentUser);
                }
            }
        });

        List<com.gr.staffpm.datatypes.Activity> recentActivities = activityDaoService.getRecentActivityForUser(currentUser);
        for (com.gr.staffpm.datatypes.Activity recentActivity : recentActivities) {
            ActivityMessage activity = new ActivityMessage(recentActivity.getTask(), new DateTime(recentActivity.getCreated()), Activity.parse(recentActivity));
            notifications.addOrReplace(new NotificationPanel(String.valueOf(recentActivity.getActivityId()), activity));
        }
        notesNewCount.setDefaultModelObject(String.valueOf(activityDaoService.getNewActivityCount(currentUser)));

        notesBoxNotif.add(notifications);
        notesBoxNotif.add(new BookmarkablePageLink<Void>("userNotesPage", AllUserNotesPage.class));
        notificationsWrapper.add(notesBoxNotif);
        notificationsWrapper.add(notesNewCount);
        add(notificationsWrapper);
    }

    protected void updateActivitiesToOld(AjaxRequestTarget target) {
        if (SecurityUtils.getSubject().isAuthenticated()) {
            List<com.gr.staffpm.datatypes.Activity> recentActivities = activityDaoService.getRecentActivityForUser(userService.getCurrentUser());
            for (com.gr.staffpm.datatypes.Activity recentActivity : recentActivities) {
                if (recentActivity.isNewNote()) {
                    recentActivity.setNewNote(false);
                    activityDaoService.updateActivity(recentActivity);
                }
            }
            notesNewCount.setDefaultModelObject(String.valueOf(0));
            target.addComponent(notificationsWrapper);
        } else
            redirectToInterceptPage(new Login());
    }

    protected void updateNotifications(AjaxRequestTarget target) {
        notifications.removeAll();
        User currUser = userService.getCurrentUser();
        List<com.gr.staffpm.datatypes.Activity> recentActivities = activityDaoService.getRecentActivityForUser(currUser);
        for (com.gr.staffpm.datatypes.Activity recentActivity : recentActivities) {
            ActivityMessage activity = new ActivityMessage(recentActivity.getTask(), new DateTime(recentActivity.getCreated()), Activity.parse(recentActivity));
            notifications.addOrReplace(new NotificationPanel(String.valueOf(recentActivity.getActivityId()), activity));
        }
        notesNewCount.setDefaultModelObject(String.valueOf(activityDaoService.getNewActivityCount(currUser)));
        target.addComponent(notificationsWrapper);
    }

    @Override
    protected void onBeforeRender() {

        Label script = new Label("script", new Model<String>()) {

            private static final long serialVersionUID = 1L;

            @Override
            protected void onComponentTagBody(MarkupStream markupStream, ComponentTag openTag) {
                StringBuffer sb = new StringBuffer();
                sb.append("notes.buildnotesmenu(\"");
                sb.append(notesBoxNotif.getMarkupId());
                sb.append("\");");
                replaceComponentTagBody(markupStream, openTag, sb.toString());
            }
        };
        notificationsWrapper.addOrReplace(script);

        super.onBeforeRender();
    }

    public boolean isOnTop() {
        return false;
    }
}
